package com.example.linktestapplication;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.LocaleManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.icu.util.TimeUnit;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.provider.Settings;
import android.text.Editable;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;

import com.example.linktestapplication.bean.HHLinkOrientation;
import com.example.linktestapplication.ble.BLEManager;
import com.example.linktestapplication.ble.OnBleConnectListener;
import com.example.linktestapplication.ble.OnDeviceSearchListener;
import com.example.linktestapplication.permission.PermissionListener;
import com.example.linktestapplication.permission.PermissionRequest;
import com.example.linktestapplication.ui.TouchSensing;
import com.example.linktestapplication.util.ClsUtils;
import com.example.linktestapplication.util.ToastUtils;
import com.example.linktestapplication.util.TypeConversion;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

public class MainActivity extends AppCompatActivity implements TouchSensing.TouchCallback {

    private static final String TAG = "BLEMain";

    //bt_patch(mtu).bin
    public static final String SERVICE_UUID = "0000ffe0-0000-1000-8000-00805f9b34fb";  //蓝牙通讯服务
    public static final String READ_UUID = "0000ffe2-0000-1000-8000-00805f9b34fb";  //读特征
    public static final String WRITE_UUID = "0000ffe1-0000-1000-8000-00805f9b34fb";  //写特征

    //动态申请权限
    private String[] requestPermissionArray = new String[]{
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.BLUETOOTH,
            Manifest.permission.BLUETOOTH_ADMIN,
            Manifest.permission.BLUETOOTH_CONNECT,
            Manifest.permission.BLUETOOTH_SCAN,
            Manifest.permission.BLUETOOTH_ADVERTISE,

    };
    // 声明一个集合，在后面的代码中用来存储用户拒绝授权的权限
    private List<String> deniedPermissionList = new ArrayList<>();

    private static final int CONNECT_SUCCESS = 0x01;
    private static final int CONNECT_FAILURE = 0x02;
    private static final int DISCONNECT_SUCCESS = 0x03;
    private static final int SEND_SUCCESS = 0x04;
    private static final int SEND_FAILURE = 0x05;
    private static final int RECEIVE_SUCCESS = 0x06;
    private static final int RECEIVE_FAILURE = 0x07;
    private static final int START_DISCOVERY = 0x08;
    private static final int STOP_DISCOVERY = 0x09;
    private static final int DISCOVERY_DEVICE = 0x0A;
    private static final int DISCOVERY_OUT_TIME = 0x0B;
    private static final int SELECT_DEVICE = 0x0C;
    private static final int BT_OPENED = 0x0D;
    private static final int BT_CLOSED = 0x0E;
    private static final int TRACK_UPPER = 0x0F;
    private static final int TRACK_DOWN = 0x11;
    private static final int TRACK_LEFT = 0x12;
    private static final int TRACK_RIGHT = 0x13;
    private static final int TRACK_START = 0x14;
    private static final int TRACK_END = 0x15;

    private Button btSearch;
    private TextView tvCurConState;
    private TextView tvName;
    private TextView tvAddress;
    private Button btConnect;
    private Button btDisconnect;
    private EditText etSendMsg;
    private Button btSend;
    private Button btTrack;
    private Button btUpper;
    private Button btDown;
    private Button btLeft;
    private Button btRight;
    private Button btPause;
    private TextView tvSendResult;
    private TextView tvReceive;
    private LinearLayout llDeviceList;
    private LinearLayout llDataSendReceive;
    private ListView lvDevices;
    private LVDevicesAdapter lvDevicesAdapter;

    private EditText et_inputUpperSpeed;
    private EditText et_inputDownSpeed;
    private EditText et_inputLeftSpeed;
    private EditText et_inputRightSpeed;

    private TouchSensing touchSensing;

    private Context mContext;
    private BLEManager bleManager;
    private BLEBroadcastReceiver bleBroadcastReceiver;
    private BluetoothDevice curBluetoothDevice;  //当前连接的设备
    //当前设备连接状态
    private boolean curConnState = false;

    private int pan;
    private int tilt;

    @SuppressLint("HandlerLeak")
    private final Handler mHandler = new Handler(Looper.getMainLooper()) {
        @SuppressLint({"SetTextI18n", "MissingPermission"})
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);

            switch (msg.what) {
                case START_DISCOVERY:
                    Log.d(TAG, "开始搜索设备...");
                    break;

                case STOP_DISCOVERY:
                    Log.d(TAG, "停止搜索设备...");
                    break;

                case DISCOVERY_DEVICE:  //扫描到设备
                    BLEDevice bleDevice = (BLEDevice) msg.obj;
                    lvDevicesAdapter.addDevice(bleDevice);

                    break;

                case SELECT_DEVICE:
                    BluetoothDevice bluetoothDevice = (BluetoothDevice) msg.obj;
                    tvName.setText(bluetoothDevice.getName());
                    tvAddress.setText(bluetoothDevice.getAddress());
                    curBluetoothDevice = bluetoothDevice;
                    break;

                case CONNECT_FAILURE: //连接失败
                    Log.d(TAG, "连接失败");
                    tvCurConState.setText("连接失败");
                    curConnState = false;
                    break;

                case CONNECT_SUCCESS:  //连接成功
                    Log.d(TAG, "连接成功");
                    tvCurConState.setText("连接成功");
                    curConnState = true;
                    llDataSendReceive.setVisibility(View.VISIBLE);
                    llDeviceList.setVisibility(View.GONE);
                    touchSensing.setVisibility(View.VISIBLE);
                    break;

                case DISCONNECT_SUCCESS:
                    Log.d(TAG, "断开成功");
                    tvCurConState.setText("断开成功");
                    curConnState = false;

                    break;

                case SEND_FAILURE: //发送失败
                    byte[] sendBufFail = (byte[]) msg.obj;
                    String sendFail = TypeConversion.bytes2HexString(sendBufFail, sendBufFail.length);
                    tvSendResult.setText("发送数据失败，长度" + sendBufFail.length + "--> " + sendFail);
                    break;

                case SEND_SUCCESS:  //发送成功
                    byte[] sendBufSuc = (byte[]) msg.obj;
                    String sendResult = TypeConversion.bytes2HexString(sendBufSuc, sendBufSuc.length);
                    tvSendResult.setText("发送数据成功，长度" + sendBufSuc.length + "--> " + sendResult);
                    break;

                case RECEIVE_FAILURE: //接收失败
                    String receiveError = (String) msg.obj;
                    tvReceive.setText(receiveError);
                    break;

                case RECEIVE_SUCCESS:  //接收成功
                    byte[] recBufSuc = (byte[]) msg.obj;
                    readData(recBufSuc, recBufSuc.length);
                    String receiveResult = TypeConversion.bytes2HexString(recBufSuc, recBufSuc.length);
                    tvReceive.setText("接收数据成功，长度" + recBufSuc.length + "--> " + receiveResult);
                    break;

                case BT_CLOSED:
                    Log.d(TAG, "系统蓝牙已关闭");
                    break;

                case BT_OPENED:
                    Log.d(TAG, "系统蓝牙已打开");
                    break;

                case TRACK_UPPER:

                    speedCtrlTrack(0, 100);
                    break;
                case TRACK_DOWN:

                    speedCtrlTrack(0, -100);
                    break;
                case TRACK_LEFT:

                    speedCtrlTrack(-100, 0);
                    break;
                case TRACK_RIGHT:

                    speedCtrlTrack(100, 0);
                    break;
                case TRACK_START:
                    speedCtrlTrack(pan, tilt);
                    break;
                case TRACK_END:
                    speedCtrlTrack(0, 0);
                    break;
            }

        }
    };


    /**
     * link 库使用：
     * 1.调用初始化--初始化主要的工作是初始化上下文环境，并且需要传入写回调和读回调（回调可自定义）
     * 2.读取设备信息--初始化之后，如需读取设备信息，需注册设备信息回调
     * 3.发送指令--根据不同的操作调用不同的封装指令即可
     * */

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mContext = MainActivity.this;

        //动态申请权限（Android 6.0）

        //初始化视图
        initView();
        //初始化监听
        iniListener();
        //初始化数据
        initData();
        //注册广播
        initBLEBroadcastReceiver();
        //初始化权限
        initPermissions();

        //初始化link库
        initLink();

    }

    private cycleThread mCycleThread;

    public int dp2px(float dpValue) {
        float scale = this.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    @Override
    public void startMove(float xAspect, float yAspect) {
        if (curConnState)
            setRemoteRockerControl(xAspect, yAspect);
        else {
            ToastUtils.showShortToast(MainActivity.this, "请先连接当前设备", Toast.LENGTH_SHORT);
        }
    }

    @Override
    public void endMove() {
        for (int i = 0; i < 3; i++) {
            mHandler.sendMessage(mHandler.obtainMessage(TRACK_END));
        }
    }

    static class SampleClick implements View.OnClickListener {
        private final boolean connect;
        private final Context context;

        public SampleClick(boolean connect, Context context) {
            this.connect = connect;
            this.context = context;
        }

        @Override
        public void onClick(View v) {
            if (!connect) {
                ToastUtils.showShortToast(context, "先连接蓝牙！", Toast.LENGTH_SHORT);
            }
        }
    }

    ;

    /**
     * 初始化视图
     */
    private void initView() {
        btSearch = findViewById(R.id.bt_search);
        tvCurConState = findViewById(R.id.tv_cur_con_state);
        btConnect = findViewById(R.id.bt_connect);
        btDisconnect = findViewById(R.id.bt_disconnect);
        tvName = findViewById(R.id.tv_name);
        tvAddress = findViewById(R.id.tv_address);
        etSendMsg = findViewById(R.id.et_send_msg);
        btSend = findViewById(R.id.bt_to_send);
        tvSendResult = findViewById(R.id.tv_send_result);
        tvReceive = findViewById(R.id.tv_receive_result);
        llDeviceList = findViewById(R.id.ll_device_list);
        llDataSendReceive = findViewById(R.id.ll_data_send_receive);
        lvDevices = findViewById(R.id.lv_devices);
        btTrack = findViewById(R.id.bt_to_track);
        btUpper = findViewById(R.id.bt_to_upper);
        btDown = findViewById(R.id.bt_to_down);
        btLeft = findViewById(R.id.bt_to_left);
        btRight = findViewById(R.id.bt_to_right);
        btPause = findViewById(R.id.bt_to_pause);

        et_inputDownSpeed = findViewById(R.id.et_input_down_speed);
        et_inputLeftSpeed = findViewById(R.id.et_input_left_speed);
        et_inputUpperSpeed = findViewById(R.id.et_input_upper_speed);
        et_inputRightSpeed = findViewById(R.id.et_input_right_speed);

        touchSensing = findViewById(R.id.touch);
        ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) touchSensing.getLayoutParams();
        layoutParams.width = getResources().getDisplayMetrics().widthPixels / 2;
        layoutParams.height = layoutParams.width;
        touchSensing.setLayoutParams(layoutParams);

        touchSensing.setTouchCallback(this);

        btTrack.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (curConnState) {
                    traceStart(true, HHLinkOrientation.LANDSCAPE_LEFT);
                    int i = 0;
                    while (i < 1000) {
                        traceUpdate(0.2f, 0.2f, 0.2f, 0.2f);
                        i++;
                    }
//                    closeMiddle();

                }
            }
        });

        mCycleThread = new cycleThread(mHandler, TRACK_START);
        mCycleThread.start();


        btRight.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (curConnState) {
                    if (et_inputRightSpeed.getText().length() <= 0
                            && et_inputRightSpeed.getText().toString().isEmpty()) {
                        pan = 300;
                    } else {
                        int inputSpeed = Integer.parseInt(et_inputRightSpeed.getText().toString());
                        pan = Math.abs(inputSpeed);
                        if (inputSpeed < -510 || inputSpeed > 510) {
                            pan = 510;
                        }
                    }
                    if (mCycleThread.getStopStatus()) {
                        mCycleThread.setStop(false);
                    }
                } else {
                    ToastUtils.showShortToast(MainActivity.this, "先连接蓝牙！", Toast.LENGTH_SHORT);
                }
            }
        });


        btUpper.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (curConnState) {
                    if (et_inputUpperSpeed.getText().length() <= 0
                            && et_inputUpperSpeed.getText().toString().isEmpty()) {
                        tilt = 300;
                    } else {
                        int inputSpeed = Integer.parseInt(et_inputUpperSpeed.getText().toString());
                        tilt = Math.abs(inputSpeed);
                        if (inputSpeed < -510 || inputSpeed > 510) {
                            tilt = 510;
                        }
                    }

                    if (mCycleThread.getStopStatus()) {
                        mCycleThread.setStop(false);
                    }
                } else {
                    ToastUtils.showShortToast(MainActivity.this, "先连接蓝牙！", Toast.LENGTH_SHORT);
                }
            }
        });

        btDown.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (curConnState) {
                    if (et_inputDownSpeed.getText().length() <= 0
                            && et_inputDownSpeed.getText().toString().isEmpty()) {
                        tilt = -300;
                    } else {
                        int inputSpeed = Integer.parseInt(et_inputDownSpeed.getText().toString());
                        tilt = -Math.abs(inputSpeed);
                        if (inputSpeed < -510 || inputSpeed > 510) {
                            tilt = -510;
                        }
                    }
                    if (mCycleThread.getStopStatus()) {
                        mCycleThread.setStop(false);
                    }
                } else {
                    ToastUtils.showShortToast(MainActivity.this, "先连接蓝牙！", Toast.LENGTH_SHORT);
                }
            }
        });

        btLeft.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (curConnState) {
                    if (et_inputLeftSpeed.getText().length() <= 0
                            && et_inputLeftSpeed.getText().toString().isEmpty()) {
                        pan = -300;
                    } else {
                        int inputSpeed = Integer.parseInt(et_inputLeftSpeed.getText().toString());
                        pan = -Math.abs(inputSpeed);
                        if (inputSpeed < -510 || inputSpeed > 510) {
                            pan = -510;
                        }
                    }

                    if (mCycleThread.getStopStatus()) {
                        mCycleThread.setStop(false);
                    }
                } else {
                    ToastUtils.showShortToast(MainActivity.this, "先连接蓝牙！", Toast.LENGTH_SHORT);
                }
            }
        });


        btPause.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i(TAG, "onClick: pause");
                pan = 0;
                tilt = 0;
                if (!mCycleThread.getStopStatus()) {
                    mCycleThread.setStop(true);
                }

                for (int i = 0; i < 3; i++) {
                    mHandler.sendMessage(mHandler.obtainMessage(TRACK_END));
                }
            }
        });


        btSearch.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i(TAG, "onClick: bt search click");
                if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
                    ToastUtils.showShortToast(MainActivity.this, "需要使用定位权限！", Toast.LENGTH_SHORT);
                    return;
                }

                if (!bleManager.isEnable()) {
                    ToastUtils.showShortToast(MainActivity.this, "需要使用蓝牙权限！", Toast.LENGTH_SHORT);
                    return;
                }

                llDataSendReceive.setVisibility(View.GONE);
                llDeviceList.setVisibility(View.VISIBLE);
                touchSensing.setVisibility(View.GONE);
                searchBtDevice();
            }
        });

        btConnect.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!curConnState) {
                    if (bleManager != null) {
                        bleManager.connectBleDevice(mContext, curBluetoothDevice, 15000, SERVICE_UUID, READ_UUID, WRITE_UUID, onBleConnectListener);
                    }
                } else {
                    ToastUtils.showShortToast(MainActivity.this, "当前设备已连接", Toast.LENGTH_SHORT);
                }
            }
        });

        btDisconnect.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (curConnState) {
                    if (bleManager != null) {
                        bleManager.disConnectDevice();
                    }
                } else {
                    ToastUtils.showShortToast(MainActivity.this, "当前设备未连接", Toast.LENGTH_SHORT);
                }
            }
        });

        btSend.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (curConnState) {
                    String sendMsg = etSendMsg.getText().toString();
                    if (sendMsg.isEmpty()) {
                        ToastUtils.showShortToast(MainActivity.this, "发送数据为空！", Toast.LENGTH_SHORT);
                        return;
                    }
                    if (bleManager != null) {
                        bleManager.sendMessage(sendMsg);  //以16进制字符串形式发送数据
                    }
                } else {
                    ToastUtils.showShortToast(MainActivity.this, "请先连接当前设备", Toast.LENGTH_SHORT);
                }
            }
        });

    }

    public static class cycleThread extends Thread {

        private boolean stop = true;
        private final Handler handler;
        private final int flag;
        private final Object sync = new Object();

        public cycleThread(Handler handler, int flag) {
            this.handler = handler;
            this.flag = flag;
        }

        @Override
        public void run() {
            super.run();
            while (!Thread.interrupted()) {

                synchronized (sync) {
                    if (stop) {
                        try {
                            Log.i(TAG, "run: wait");
                            sync.wait();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }

                if (handler != null) {
                    handler.sendMessage(handler.obtainMessage(flag));
                    try {
                        sleep(50);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }

        public void setStop(boolean stop) {
            synchronized (sync) {
                sync.notify();
                this.stop = stop;
                Log.i(TAG, "setStop: stop = " + stop);
            }
        }

        public boolean getStopStatus() {
            return stop;
        }
    }


    @SuppressLint("MissingPermission")
    public void getBaseInfo(View view) {
        if (curConnState) {
            testQueryAttributeCallback queryAttributeCallback = new testQueryAttributeCallback();
            connect(curBluetoothDevice.getName(), curBluetoothDevice.getAddress(), queryAttributeCallback);
            startActivity(new Intent(MainActivity.this, BaseInfoActivity.class));
        } else {
            ToastUtils.showShortToast(this, "请先连接蓝牙！", Toast.LENGTH_SHORT);
        }
    }

    public void clickMiddle(View view) {
        if (curConnState) {
            closeMiddle();
        } else {
            ToastUtils.showShortToast(this, "请先连接蓝牙！", Toast.LENGTH_SHORT);
        }
    }

    /**
     * 初始化监听
     */
    private void iniListener() {
//        btSearch.setOnClickListener(this);
//        btConnect.setOnClickListener(this);
//        btDisconnect.setOnClickListener(this);
//        btSend.setOnClickListener(this);


        lvDevices.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                Log.i(TAG, "onItemClick: item click");
                BLEDevice bleDevice = (BLEDevice) lvDevicesAdapter.getItem(i);
                BluetoothDevice bluetoothDevice = bleDevice.getBluetoothDevice();
                if (bleManager != null) {
                    bleManager.stopDiscoveryDevice();
                }

                Message message = new Message();
                message.what = SELECT_DEVICE;
                message.obj = bluetoothDevice;
                mHandler.sendMessage(message);
            }
        });
    }

    /**
     * 初始化数据
     */
    private void initData() {
        //列表适配器
        lvDevicesAdapter = new LVDevicesAdapter(MainActivity.this, new LVDevicesAdapter.itemClick() {
            @Override
            public void click(int i) {
                Log.i(TAG, "click: item click");
                BLEDevice bleDevice = (BLEDevice) lvDevicesAdapter.getItem(i);
                BluetoothDevice bluetoothDevice = bleDevice.getBluetoothDevice();
                if (bleManager.isDiscovery()) {
                    bleManager.stopDiscoveryDevice();
                }
//                mHandler.removeCallbacksAndMessages(null);

                Message message = new Message();
                message.what = SELECT_DEVICE;
                message.obj = bluetoothDevice;
                mHandler.sendMessage(message);
            }
        });
        lvDevices.setAdapter(lvDevicesAdapter);

        //初始化ble管理器
        bleManager = new BLEManager();
        if (!bleManager.initBle(mContext)) {
            ToastUtils.showShortToast(mContext, "该设备不支持低功耗蓝牙", Toast.LENGTH_SHORT);
        } else {
            if (!bleManager.isEnable()) {
                //去打开蓝牙
                bleManager.openBluetooth(mContext, false);
            }
        }
    }


    /**
     * 注册广播
     */
    private void initBLEBroadcastReceiver() {
        //注册广播接收
        bleBroadcastReceiver = new BLEBroadcastReceiver();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED); //开始扫描
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//扫描结束
        intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);//手机蓝牙状态监听
        registerReceiver(bleBroadcastReceiver, intentFilter);
    }



    private LocationManager locationManager;

    /**
     * 初始化权限
     */
    @SuppressLint("MissingPermission")
    private void initPermissions() {
        //Android 6.0以上动态申请权限

        locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
        if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) && !locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
            ToastUtils.showShortToast(MainActivity.this, "定位未打开！", Toast.LENGTH_SHORT);
        }

        final PermissionRequest permissionRequest = new PermissionRequest();
        permissionRequest.requestRuntimePermission(MainActivity.this, requestPermissionArray, new PermissionListener() {
            @Override
            public void onGranted() {
                Log.d(TAG, "所有权限已被授予");
            }

            //用户勾选“不再提醒”拒绝权限后，关闭程序再打开程序只进入该方法！
            @Override
            public void onDenied(List<String> deniedPermissions) {
                deniedPermissionList = deniedPermissions;
                for (String deniedPermission : deniedPermissionList) {
                    Log.e(TAG, "被拒绝权限：" + deniedPermission);
                }
            }
        });
    }


    private void initLink() {
        writeFnCallback writeFnCallback = new testCallbackImp(bleManager);
        readFnCallback readFnCallback = new testReadCallbackImp();
        testEventCallback testEventCallback = new testEventCallback();

        initResource(writeFnCallback, readFnCallback, testEventCallback);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        //注销广播接收
        unregisterReceiver(bleBroadcastReceiver);
    }

    //////////////////////////////////  搜索设备  /////////////////////////////////////////////////
    private void searchBtDevice() {
        if (bleManager == null) {
            Log.d(TAG, "searchBtDevice()-->bleManager == null");
            return;
        }

        if (bleManager.isDiscovery()) { //当前正在搜索设备...
            bleManager.stopDiscoveryDevice();
        }

        if (lvDevicesAdapter != null) {
            lvDevicesAdapter.clear();  //清空列表
        }

        //开始搜索
        bleManager.startDiscoveryDevice(onDeviceSearchListener, 5000);
    }

    //扫描结果回调
    private OnDeviceSearchListener onDeviceSearchListener = new OnDeviceSearchListener() {

        @Override
        public void onDeviceFound(BLEDevice bleDevice) {
            Message message = new Message();
            message.what = DISCOVERY_DEVICE;
            message.obj = bleDevice;
            mHandler.sendMessage(message);
        }

        @Override
        public void onDiscoveryOutTime() {
            Message message = new Message();
            message.what = DISCOVERY_OUT_TIME;
            mHandler.sendMessage(message);
        }
    };

    //连接回调
    private OnBleConnectListener onBleConnectListener = new OnBleConnectListener() {
        @Override
        public void onConnecting(BluetoothGatt bluetoothGatt, BluetoothDevice bluetoothDevice) {

        }

        @Override
        public void onConnectSuccess(BluetoothGatt bluetoothGatt, BluetoothDevice bluetoothDevice, int status) {
            //因为服务发现成功之后，才能通讯，所以在成功发现服务的地方表示连接成功
        }

        @Override
        public void onConnectFailure(BluetoothGatt bluetoothGatt, BluetoothDevice bluetoothDevice, String exception, int status) {
            Message message = new Message();
            message.what = CONNECT_FAILURE;
            mHandler.sendMessage(message);
        }

        @Override
        public void onDisConnecting(BluetoothGatt bluetoothGatt, BluetoothDevice bluetoothDevice) {

        }

        @Override
        public void onDisConnectSuccess(BluetoothGatt bluetoothGatt, BluetoothDevice bluetoothDevice, int status) {
            Message message = new Message();
            message.what = DISCONNECT_SUCCESS;
            message.obj = status;
            mHandler.sendMessage(message);
        }

        @Override
        public void onServiceDiscoverySucceed(BluetoothGatt bluetoothGatt, BluetoothDevice bluetoothDevice, int status) {
            //因为服务发现成功之后，才能通讯，所以在成功发现服务的地方表示连接成功
            Message message = new Message();
            message.what = CONNECT_SUCCESS;
            mHandler.sendMessage(message);
        }

        @Override
        public void onServiceDiscoveryFailed(BluetoothGatt bluetoothGatt, BluetoothDevice bluetoothDevice, String failMsg) {
            Message message = new Message();
            message.what = CONNECT_FAILURE;
            mHandler.sendMessage(message);
        }

        @Override
        public void onReceiveMessage(BluetoothGatt bluetoothGatt, BluetoothDevice bluetoothDevice, BluetoothGattCharacteristic characteristic, byte[] msg) {
            Message message = new Message();
            message.what = RECEIVE_SUCCESS;
            message.obj = msg;
            mHandler.sendMessage(message);
        }

        @Override
        public void onReceiveError(String errorMsg) {
            Message message = new Message();
            message.what = RECEIVE_FAILURE;
            mHandler.sendMessage(message);
        }

        @Override
        public void onWriteSuccess(BluetoothGatt bluetoothGatt, BluetoothDevice bluetoothDevice, byte[] msg) {
            Message message = new Message();
            message.what = SEND_SUCCESS;
            message.obj = msg;
            mHandler.sendMessage(message);
        }

        @Override
        public void onWriteFailure(BluetoothGatt bluetoothGatt, BluetoothDevice bluetoothDevice, byte[] msg, String errorMsg) {
            Message message = new Message();
            message.what = SEND_FAILURE;
            message.obj = msg;
            mHandler.sendMessage(message);
        }

        @Override
        public void onReadRssi(BluetoothGatt bluetoothGatt, int Rssi, int status) {

        }

        @Override
        public void onMTUSetSuccess(String successMTU, int newMtu) {

        }

        @Override
        public void onMTUSetFailure(String failMTU) {

        }
    };


    /**
     * 蓝牙广播接收器
     */
    private class BLEBroadcastReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (TextUtils.equals(action, BluetoothAdapter.ACTION_DISCOVERY_STARTED)) { //开启搜索
                Message message = new Message();
                message.what = START_DISCOVERY;
                mHandler.sendMessage(message);

            } else if (TextUtils.equals(action, BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {//完成搜素
                Message message = new Message();
                message.what = STOP_DISCOVERY;
                mHandler.sendMessage(message);

            } else if (TextUtils.equals(action, BluetoothAdapter.ACTION_STATE_CHANGED)) {   //系统蓝牙状态监听

                int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0);
                if (state == BluetoothAdapter.STATE_OFF) {
                    Message message = new Message();
                    message.what = BT_CLOSED;
                    mHandler.sendMessage(message);

                } else if (state == BluetoothAdapter.STATE_ON) {
                    Message message = new Message();
                    message.what = BT_OPENED;
                    mHandler.sendMessage(message);

                }
            }
        }

    }


    // Used to load the 'linktestapplication' library on application startup.
    static {
        System.loadLibrary("linktestapplication");
    }

    /**
     * A native method that is implemented by the 'linktestapplication' native library,
     * which is packaged with this application.
     */
    public native String stringFromJNI();

    /**
     * 初始化link库
     */
    public static native void initResource(writeFnCallback writeFnCallback,
                                           readFnCallback readFnCallback,
                                           eventFnCallback eventFnCallback);

    //释放link库
    public static native void release();

    //添加连接信息
    public static native void connect(String cname, String cmac, queryAttributeFnCallback queryAttributeFnCallback);

    //初始化轨迹跟随
    public static native void traceStart(boolean isCameraFront, HHLinkOrientation orientation);

    //更新轨迹位置
    public static native void traceUpdate(float centerX, float centerY, float w, float h);

    //结束轨迹跟随
    public static native void traceEnd();

    //居中
    public static native void closeMiddle();

    //读取返回数据
    public static native void readData(byte[] data, int length);

    //设置移动速度，如果速度大于零则开始移动，如设置速度为零，则会由当前速度缓慢减速为零
    public static native void speedCtrlTrack(int pan, int tilt);

    //设置俯仰移动方向
    public static native void setCtrlTrackOri(int reverse);

    //获取俯仰移动方向
    public static native int getCtrlTrackOri();

    //遥感控制
    public static native void setRemoteRockerControl(float x, float y);


    public native void set();


    //蓝牙写数据
    public interface writeFnCallback {
        void writeFn(byte[] buffer, int length, boolean isReponse);
    }

    //蓝牙读数据
    public interface readFnCallback {
        void notifyReadFn();
    }

    //超时
    public interface timeoutFnCallback {
        void timeout();
    }

    //蓝牙返回数据-物理硬件按键数据
    public interface eventFnCallback {
        void handleEvent(int eventId);
    }

    //查询云台信息
    public interface queryAttributeFnCallback {
        void queryStatus(boolean result, boolean isBusy);
    }

    // 云台校准的回调函数
    public interface calibrateResultFnCallback {
        void calibrateStatus(int state);
    }

    // 恢复出厂设置回调函数
    public interface resetFactoryResultFnCallback {
        void resetResult(int code);
    }


    public static class testCallbackImp implements writeFnCallback {

        private final BLEManager bleManager;

        public testCallbackImp(BLEManager bleManager) {
            this.bleManager = bleManager;
        }

        @Override
        public void writeFn(byte[] buffer, int length, boolean isReponse) {

            Log.i(TAG, "writeFn: handle callback! buffer = " + TypeConversion.bytes2HexString(buffer, length));

            if (bleManager != null) {
//                String string = new String(buffer);
//                bleManager.sendMessage(string.getBytes(StandardCharsets.UTF_8));
                bleManager.sendMessage(buffer);
            }
        }
    }


    public static class testReadCallbackImp implements readFnCallback {

        @Override
        public void notifyReadFn() {
            Log.i(TAG, "notifyReadFn: handle read callback!");
        }
    }


    public static class testEventCallback implements eventFnCallback {

        @Override
        public void handleEvent(int eventId) {
            Log.i(TAG, "handleEvent: handle event callback ! id = " + eventId);


        }
    }


    public static class testQueryAttributeCallback implements queryAttributeFnCallback {

        @Override
        public void queryStatus(boolean result, boolean isBusy) {
            Log.i(TAG, "queryStatus: result = " + result);
        }
    }

}